<!DOCTYPE html>
   <html>
   <head>
       <meta charset="utf-8">
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <title></title>
       <link rel="stylesheet" href="">
        <script type="text/javascript">
        /*1.写一个函数判断一个数组，如果数组里面有负值，函数返回false,否则函数返回true
            var a=[1,0,5,7,5,-6];
            function test(arr){
                var obj=null;
                for(var i=0;i<arr.length;i++){

                    if(arr[i]<0){
                        console.log(arr[i]+'<0');
                        obj=false;
                        break;

                    }else{
                        console.log(arr[i]+'>=0');
                        obj=true;

                    }

                }
                return obj;
            }
            alert(test(a));
            */
            // 方法2
            // var a=[1,0,5,7,5,-6];
            // var result=a.some(function(item){
            //     if(item<0){
            //         return false
            //     }else{
            //         return true
            //     }
            // })
            // console.log(result) // false
           /*
        //2.求出一个字符串中出现最多字母的长度
            var str='aaabbbccccccccddfgh';

            function test(str){
                var arr=str.split('');
                var num=0;
                var value = '';
                //console.log(arr);
                var obj={};
                arr.forEach(function(n,i){//n代表数组中每一个值,i代表下标

                    if( !obj[ arr[i] ] ){//如果对象的键值不存在，就创建一个新的键值对
                        obj[ arr[i] ]=[];
                    }
                    obj[ arr[i] ].push( arr[i] );

                })
                for(var x in obj){//x代表键
                    //console.log(obj[x].length);
                    if(num < obj[x].length){
                        num =obj[x].length;
                        value=obj[x][0];
                    }
                }
                console.log('该字符串中'+value+'最多,数量为'+num+'个');
            }
            test(str);
            */
        /*
        //3.两个数组同时指向一个引用地址，改变其中一个，要求另外一个不改变
        var a=[1,2,3];
        var b=a;
        var c=a.slice(0);

        a.push(4);
        alert(b);//和a指向同一个引用地址，a变化，b也跟着变   1,2,3,4
        alert(c);//构建一个数组的拷贝,而不是引用
        */
        /*
        //4.对象的复制及深拷贝
            var a={
                a:1,
                b:2
            };
            //alert(a['a']);//1
            var b=a;

            function clone(obj){
                var newobj={};
                for(var x in obj){
                    newobj[x]=obj[x];
                }
                return newobj;
            }
            var c=clone(a);

            a.a=100;
            console.log(b);
            console.log(c);

            //深拷贝
            function deepclone(obj,newobj){
                var newobj=newobj||{};
                for(var i in obj){
                    if(typeof obj[i]=='object'){
                        newobj[i]=(obj[i].constructor===Array)?[]:{};
                        deepclone(obj[i],newobj[i])
                    }else{
                        newobj[i]=obj[i]
                    }
                }
                return newobj;
            }
            */
        //5.判断一个变量是数组
        /*
            var a=[1,12,4];
            alert(typeof a);//obj无法判断是否是一个数组
            alert(a instanceof Array);//判断a是否是数组的一个实例
            console.log(a.__proto__.constructor==Array);
            console.log(a.constructor==Array);//constructor指向其构造函数
        */
        /**

        */

        //6.闭包用法

            // function mo(){
            //     var x=0;
            //     return function(){
            //         console.log(++x);//先执行++,再打印
            //         console.log(x+'-----')
            //     }
            // }
            // var a=mo();
            // var b=mo();
            // console.log(a());//1
            // console.log(a());//2
            // console.log(a());//3
            // console.log(b());//1

        //7.原型用法，修改了对象，其原型不会受影响
        /*
            var p=[];
            var A=function(){};
            A.prototype=p;
            var a=new A;
            //console.log(typeof a);
            a.push(1);

            console.log(a.length);//1
            console.log(p.length);//0
        */
        //8.二维数组转一维数组
        // var arr=[[1,2,3],[3,4],[5],4668];
        // console.log([].concat.apply([],arr));//方法1

        // function unid(arr){  //方法2
        //     console.log(arr+'');//1,2,3,3,4,5,4668
        //     var arr1 = (arr + '').split(',');//将数组转字符串后再以逗号分隔转为数组
        //     console.log(arr1)  // ["1", "2", "3", "3", "4", "5", "4668"]
        //     var arr2 = arr1.map(function(x){
        //         return Number(x);
        //     });
        //     return arr2;
        // }
        // console.log(unid(arr));

            //方法2
            // let arr = [[0, 1], [2, 3], [4, 5]]
            // let newArr = arr.reduce((pre,cur)=>{
            //     return pre.concat(cur)
            // },[])
            // console.log(newArr); // [0, 1, 2, 3, 4, 5]

            //方法3
            // let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
            // const newArr = function(arr){
            //     return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
            // }
            // console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]

            方法4
            arr.join().split(',')
        //9.给一组数字添加千分符
            //1.先将该字符串%3,得出前面多余的几位数字；
            //2.创建一个新数组，将上一步得到的数字外的所有数字放进数组里
          /*
            var str='76584959643';
            function test(str){
                var num=str.length%3;
                var arr=[];
                var inow=0;
                var temp='';
                var str1=str.substring(num);// '584959643'

                if(num!=0){
                    arr.push(str.substring(0,num));
                };
                //console.log(arr) //['76']
                for( var i = 0;i<str1.length;i++){
                    inow++;
                    temp+=str1[i];
                    if(inow==3){
                        arr.push(temp);
                        inow=0;
                        temp='';
                    }
                }
                console.log(arr)
                var newstr=arr.join(',');
                return newstr;

            }
            console.log(test(str));
            */
        // 10.冒泡算法
        // var arr=[5,2,4,8,9,0,1,3,6,7]

        // for(var i=0;i<arr.length;i++){

        //     for(var j=i+1;j<arr.length;j++){
        //         if(arr[i]<arr[j]){
        //             var tmp=arr[i];
        //             arr[i]=arr[j];
        //             arr[j]=tmp;

        //         }
        //     }
        // }
        // console.log(arr)
        // 11.找出最小值
        // var arr=[5,2,4,8,9,0,1,3,6,7,12]
        // var min=arr[0]
        // var minaddress=0;
        // for(var i=0;i<arr.length;i++){
        //     if(arr[i]<min){
        //         min=arr[i]

        //     }

        // }
        // for (var a=0;a<arr.length;a++){
        //     if(arr[a]==min){
        //         minaddress=a;
        //     }
        // }
        // console.log(`最小值为${min},下标为${minaddress}`)
        
        //11.数组去重
            //var arr=['1','v','a',1,3,4,2,1,4,2,1,'b','a'];
            //方法1
            // function remove(arr){
            //     var newarr=[];
            //     for(var i=0;i<arr.length;i++){
            //         if(newarr.indexOf(arr[i])==-1){
            //             newarr.push(arr[i])
            //         }
            //     }
            //     return newarr;
            // }
            // console.log(remove(arr))
            //方法2
            // function remove2(arr){
            //     var obj={};
            //     var newarr=[];
            //     for(var i=0;i<arr.length;i++){
            //         if(!obj[arr[i]]){
            //             obj[arr[i]]=1;
            //             newarr.push(arr[i]);
            //         }
            //     }
                
            //     return newarr;

            // }
            // console.log(remove2(arr))
            // 方法3
            // var arr=[1,4,'a',2,54];
            // var s2=new Set(arr);
            // var newarr=[...s2];

            //方法4
            // let arr = [1,2,3,4,4,1]
            // let newArr = arr.reduce((pre,cur)=>{
            //     if(!pre.includes(cur)){
            //     return pre.concat(cur)
            //     }else{
            //     return pre
            //     }
            // },[])
            // console.log(newArr);// [1, 2, 3, 4]
        //12.call用法(借用别的函数实现自身的方法，并改变this指向)
            // function foo(){
            //     bar.apply(null,arguments);
            // }
            // function bar(x){
            //     console.log(arguments)
            // }
            // foo(1,2,3,4);//[1,2,3,4]
        //13.
            // var a=5;
            // function test(){
            //     a=0;
            //     console.log(a);
            //     console.log(this.a);
            //     var a;
            //     console.log(a);

            // }
            // test();// 0 5 0
            // //var test1=new test();//0 undefined 0
        //14.利用原型实现一个继承的实例
            // window.onload=function(){
            //     function Ele(id){
            //         this.ele=document.getElementById(id);
            //     }
            //     Ele.prototype.html=function(val){
            //         var elem=this.ele;
            //         if(val){
            //             elem.innerHTML=val;
            //             return this;//可以实现链式调用
            //         }else{
            //             return elem.innerHTML;
            //         }
            //     }
            //     var el = new Ele('div1');
            //     console.log(el.html())
            // }
        

        //15. js实现继承的几种方法(https://www.jb51.net/article/179707.htm)

            //1.原型链继承,将父类的实例作为子类的原型,缺点：过多的继承了父级无用的属性
            // Person.prototype.lastName='lu';
            // function Person(){}
            // function Stu(){}

            // Stu.prototype=new Person();    
            // var stu=new Stu();
            // console.log(stu.lastName)

            //2.call继承，缺点：1.后代的所需要的属性必须完全包括父级,2.每次构造函数都要多走一个函数
            // function Person(name,age,color){
            //     this.name=name;
            //     this.age=age;
            //     this.color=color;
            // }

            // function Stu(name,age,color,grade){
            //     Person.call(this,name,age,color);
            //     this.grade=grade;
            // }

            // var stu=new Stu('zhangsan',20,'red','三年级');

            // 3.共享原型，只会继承父级原型上的属性和方法，
            // Person.prototype.name="jixiang";

            // function Person (){}

            // function Stu(){}
            // Stu.prototype=Person.prototype;
            // var stu=new Stu();
            // console.log(stu.name);

            // 4.圣杯模式
            // Person.prototype.name="jixiang";
            // function Person(){}

            // function Stu(){}

            // var inherit=(function (){
            //     var F=function(){}
            //     return function(target,origin){
            //         F.prototype=origin.prototype;
            //         target.prototype=new F();
            //         target.prototype.constructor=target;
            //     }
                
            // })();
            // inherit(Stu,Person);
            // var stu=new Stu();

            //拷贝继承(属性通过call继承，方法通过共享原型继承)
				// function Person(name) {
				// 	this.name = name
				// }
				// Person.prototype.showName = function(){
				// 	alert( this.name )
				// }
				// var p1 = new Person('小明');

				// function Star(name,job) {
				// 	Person.call( this,name)  //star 这个类通过call继承Person类的属性
				// 	this.job = job
				// }
				// //Star.prototype = Person.prototype;  //通过共享原型链继承Person的方法，此办法会有弊端：

				// //弊端：如果给Star.prototype继续添加方法，由于是对象引用，会导致person.prototype也会相应的添加该方法，这显然是不需要的

				// //解决办法：深度拷贝原型给子原型
				// function deepclone(obj,newobj){
			 //        var newobj=newobj||{};
			 //        for(var i in obj){
			 //            if(typeof obj[i]=='object'){
			 //                newobj[i]=(obj[i].constructor===Array)?[]:{};
			 //                deepclone(obj[i],newobj[i])
			 //            }else{
			 //                newobj[i]=obj[i]
			 //            }
			 //        }
			 //        return newobj;
			 //    }
				// deepclone( Person.prototype, Star.prototype )
				// Star.prototype.showjob = function() {
				// 	alert(this.job)
				// }


				// var star = new Star('黄晓明','演员');

			//类继承
				// function Person() {
				// 	this.name = '小强'
				// }
				// Person.prototype.showName = function(){
				// 	alert( this.name )
				// }
				// var p1 = new Person();

				// function Star() {
				// 	Person.call(this)   //属性依然使用方法继承
				// }
				// var F = function() {}
				// F.prototype = Person.prototype;
				// Star.prototype = new F();   .//解决问题2

				// Star.prototype = new Person();//一句话实现属性和方法的继承，但有以下几点问题
				// // 1.Star的constructor被改写
				// // 2.如果属性为引用对象，修改子的属性也会修改父级
				// Star.prototype.constructor = Star;  //解决问题1


				// var s1= new Star()	
				
			//原型继承
				// var a = {
				// 	name : '陈赫'
				// }

				// var b = cloneObj(a);

				// function cloneObj(parentObj) {
				// 	var F = function() {}
				// 	F.prototype = parentObj;
				// 	return new F();
				// }
				// alert(b.name)

			//拷贝继承： 有没有new都可以
			//类式继承： 父对象为new构造函数
			//原型继承： 父对象为无new的对象
        // 16.命名空间

            // var add=(function(){
            //     var x,y;
            //     function myadd(num1,num2){
            //         x=num1;
            //         y=num2;
            //         console.log(x+y);

            //     }
            //     return function(num1,num2){
            //         myadd(num1,num2);
            //     }
            // })();
            // console.log(add);//add结果：function (num1,num2){
            //                             //    myadd(num1,num2);
            //                             //}
            // add(1,2) //add执行，myadd会执行
            
        
        //17.函数节流,一段时间内仅进行一次操作，例如：多次点击按钮，但一定时间内只执行一次

            // window.onload=function(){
            //     var num=0;
            //     var btn=document.getElementById("btn");
            //     var odiv=document.getElementById("odiv");
            //     function buy(e){
            //         console.log(e)
            //         num++;
            //         odiv.innerHTML=num;
            //     }

            //     function jieliu(handler,wait){
            //         var starT=0;
            //         return function(){
            //             console.log(arguments)
            //             var lastT=new Date().getTime();
            //             if(lastT-starT>wait){
            //                 handler.apply(this,arguments);
            //                 starT=lastT;
            //             }
            //         }
            //     }

            //     btn.onclick=jieliu(buy,1000);
            // }  


        // 18.函数防抖，达到一定条件后，才执行一件事情，例如：百度自动查询补全功能，连续快速输入时，不会触发事件，只有连续输入暂停一定时间才执行某个事件
            // window.onload=function () {
            //     var oinp=document.getElementById('oinp');

            //     function ajax(e){
            //         console.log(e) //事件对象
            //         console.log(this.value)
            //     }
            //     function fangdou(handler,delay){
            //         var timer=null;
            //         return function(){
            //             var _self=this;
            //             var _args=arguments;
            //             clearTimeout(timer);
            //             timer=setTimeout(function(){
            //                 handler.apply(_self,_args)
            //             },delay) 
            //         }
            //     }
            //     oinp.onkeyup=fangdou(ajax,2000);
            // }

        // 19.类数组对象,1.属性要为数字索引 2.必须有length属性 3.最好加上push方法

            // var obj={
            //     "0":"a",
            //     "1":"b",
            //     "2":"c",
            //     "length":3,
            //     "push":Array.prototype.push,
            //     "splice":Array.prototype.splice  //一旦加上splice属性，该类数组对象就长的像一个数组了，可以当数组一样使用,但还不是数组，obj instanceof Array  false
            // }

            //obj.push('d');  //结果：{0: "a", 1: "b", 2: "c", 3: "d", length: 4}

            //console.log(obj)

            // Array.prototype.push=function (target){
            //     this[this.length]=target;
            //     this.length++
            // }

            // var obj1={
            //     "2":"a",
            //     "3":"b",
            //     "length":2,
            //     "push":Array.prototype.push
            // }
            // obj1.push('c')
            // obj1.push('d')

            // console.log(obj1)  //{2: "c", 3: "d", length: 4}

            //20,类型转换
            	//隐式类型转换
            	console.log(isNaN('abc')) //true 首先会隐式的调用Number('abc'),结果得出NaN，所以结果就是true
            	console.log(isNaN(null))   //false  ,因为Number(null)结果是0，Number(undefined)结果为NaN
            //21.前端优化
                // 1.html
                //     a.语义化标签
                //     b.避免dom数量及深度
                //     c.css,js正确放置位置
                //     d.压缩
                //     e.避免页面中空的 href 和 src
                // 2.css
                //     a.css3动画
                //     b.分情况外部引用或内联
                //     c.压缩
                // 3.javascript
                //     a.缓存dom
                //     b.懒加载
                //     c.预加载
                //     d.压缩
                //     e.减少作用域链查找
                //     d.get请求
                // 4.图片
                //     a.压缩
                //     b.使用css图标或者svg替代图片
                //     c.spring
                //     d.加载前预先设置宽高
                // 5.网络请求
                //     a.cdn加速
                //     b.为 HTML 指定 Cache-Control 或 Expires

            //22.p:nth-child(2)代表p的父元素下面的第二个子元素，且该元素为p标签
              // 可以参考：https://zhuanlan.zhihu.com/p/126681521
        </script>
        <style type="text/css">
            *{margin:0;padding:0;}
            .box{height:200px;background:#eee;display:flex;}

            //.box div{flex:1;}
            .left,.right{width:200px;height:200px;flex:0 1 200px;}
            .left{
                background: red;
            }
            .right{
                order:2;
                background: green;
            }
            .main{flex:auto;order:1;word-break: break-all;}
        </style>
   </head>
   <body>
       <div class="box" id="div1">
           <div class="main" >

                圣杯布局qwertyuklkjgASDFGHJKLKJHGFDSASDFJKLTREWERTYUKL;LKJHGFDSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYUIOIUYTDCV
            </div>
           <div class="left"></div>
           <div class="right"></div>
       </div>

       <input type="text" id="oinp"></input>
   </body>
   </html>
